package outPut

import (
	"errors"
	"fmt"
	"github.com/fatih/color"
	"reflect"
	"strconv"
	"strings"
)

func continueAction(jsonTag string) bool {
	var BC bool
	//
	for _, va := range []string{"", "-", "rows", "sync", "struct", "object", "task", "load", "hotsql"} {
		if strings.EqualFold(jsonTag, va) {
			BC = true
		}
	}
	return BC
}

var colorMap = map[int]reflect.Value{
	0: reflect.ValueOf(color.RedString),
	1: reflect.ValueOf(color.GreenString),
	2: reflect.ValueOf(color.YellowString),
}

func dynamicModifyValue(s any, pods string, value any) (err error) {
	val := reflect.ValueOf(s).Elem() //get value
	tType := val.Type()              //get the type of val
	for i := 0; i < tType.NumField(); i++ {
		field := tType.Field(i)
		//check if the Json Name matches the pods input
		jsonName := field.Tag.Get("json")
		if jsonName != pods {
			continue
		}
		newVal := reflect.ValueOf(value)
		if newVal.Type().AssignableTo(field.Type) {
			fieldValue := val.Field(i)
			switch {
			default:
				fieldValue.Set(newVal)
			}
			return
		}
		err = errors.New(fmt.Sprintf("input Value:%v json name: %v Type mismatch: cannot assign %v to %v\n", reflect.TypeOf(s), jsonName, newVal.Type(), field.Type))
		return
	}
	return
}

/*
RecursiveStructJsonName
获取struct的列信息，且只输出json 标签的列名，并返回[]any
input:

	type MyStruct struct {
		Field1 int    `json:"field_1"`
		Field2 string `json:"field_2"`
		Field3 bool   `json:"field_3"`
		Field4 float64
	}

output:

	[]any{field_1,field_2,field_3}
*/
func RecursiveStructJsonName(mode string, s any) []any {
	var rowC []any
	objValue := reflect.ValueOf(s)
	if objValue.Kind() == reflect.Ptr {
		objValue = objValue.Elem()
	}
	if objValue.Kind() != reflect.Struct {
		//return nil, fmt.Errorf("传入的参数必须是结构体类型")
	}
	objType := objValue.Type()
	data := make(map[string]any)
	for i := 0; i < objValue.NumField(); i++ {
		field := objValue.Field(i)
		fieldType := objType.Field(i)
		fieldName := fieldType.Name
		jsonTag := fieldType.Tag.Get("json")
		if fieldType.Type.Kind() == reflect.Struct {
			if mode == jsonTag {
				rowC = append(rowC, RecursiveStructJsonName(mode, field.Interface())...)
			}
		}
		if continueAction(jsonTag) {
			continue
		}
		fieldName = jsonTag
		rowC = append(rowC, fieldName)
		data[fieldName] = field.Interface()
	}
	return rowC
}

// RecursiveStructJsonValue 将结构体字段的值按顺序转换为切片，同时将 *int64 类型的值转换为字符串
func RecursiveStructJsonValue(mode string, s any) (slice []any) {
	value := reflect.ValueOf(s)
	if value.IsValid() && value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	objType := value.Type()
	if value.Kind() != reflect.Struct {
		return nil
	}
	for i := 0; i < value.NumField(); i++ {
		fieldValue := value.Field(i)
		//获取颜色函数的代码
		var colorCode int
		var oValue string
		if i+1 > len(colorMap) {
			colorCode = (i + 1) % len(colorMap)
		} else {
			colorCode = i
		}
		jsonTag := objType.Field(i).Tag.Get("json")
		switch {
		case fieldValue.Kind() == reflect.Ptr && fieldValue.Type().Elem().Kind() == reflect.Int64: // 检查字段类型是否为 *int64
			// 将 *int64 转换为字符串
			if fieldValue.IsNil() {
				//slice[i] = ""
				slice = append(slice, "")
			} else {
				int64Value := fieldValue.Elem().Int()
				oValue = strconv.FormatInt(int64Value, 10)
			}
		case fieldValue.Kind() == reflect.Struct:
			if mode == jsonTag {
				slice = append(slice, RecursiveStructJsonValue(mode, fieldValue.Interface())...)
			}
		case fieldValue.Kind() == reflect.Int:
			oValue = strconv.Itoa(fieldValue.Interface().(int))
		case fieldValue.Kind() == reflect.Int64:
			oValue = strconv.FormatInt(fieldValue.Interface().(int64), 10)
		case fieldValue.Kind() == reflect.Float64:
			oValue = strconv.FormatFloat(fieldValue.Interface().(float64), 'f', -1, 64)
		case fieldValue.Kind() == reflect.Bool:
			oValue = strconv.FormatBool(fieldValue.Interface().(bool))
		default:
			oValue = fieldValue.Interface().(string)
		}
		if continueAction(jsonTag) {
			continue
		}
		if funcName, ok := colorMap[colorCode]; ok {
			if funcName.Kind() == reflect.Func {
				args := []reflect.Value{
					reflect.ValueOf(oValue),
				}
				for _, v := range funcName.Call(args) {
					slice = append(slice, v.Interface())
				}
			}
		}
	}
	return
}
